using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Reflection;
using Camalon.ColorPicker.Properties;

namespace Camalon.ColorPicker
{
	/// <summary>
	/// Summary description for MouseTracker.
	/// </summary>
	internal class MouseTracker : System.Windows.Forms.Form
	{
		/// <summary>
		/// Required designer variable.
		/// </summary>
		private System.ComponentModel.Container components = null;

		public MouseTracker():this( true )
		{
		}

		public MouseTracker(bool mouseCaptured)
		{
            this.SetStyle(ControlStyles.DoubleBuffer, true);
            this.SetStyle(ControlStyles.UserPaint, true);
            //this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);

			_captureMouse = mouseCaptured;
			InitializeComponent();

		}

		/// <summary>
		/// Clean up any resources being used.
		/// </summary>
		protected override void Dispose( bool disposing )
		{
			if( disposing )
			{
				if(components != null)
				{
					components.Dispose();
				}
			}
			base.Dispose( disposing );
		}

		#region Windows Form Designer generated code
		/// <summary>
		/// Required method for Designer support - do not modify
		/// the contents of this method with the code editor.
		/// </summary>
		private void InitializeComponent()
		{
			// 
			// MouseTracker
			// 
			this.AutoScaleBaseSize = new System.Drawing.Size(5, 13);
			this.ClientSize = new System.Drawing.Size(108, 104);
			this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
			this.Name = "MouseTracker";
			this.ShowInTaskbar = false;
			this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Hide;
			this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;

		}
		#endregion


		Timer _timer = new Timer();
	
		protected override void OnLoad(EventArgs e)
		{
            this.Cursor = new Cursor(new System.IO.MemoryStream(Resources.MouseTracker));


			base.OnLoad(e);
			this.TopMost = true;
			this.Size = new Size(100,100);

			Random random= new Random(0);
			int r = random.Next( 255 );
			int g = random.Next( 255 );
			int b = random.Next( 255 );
			this.BackColor = Color.FromArgb( r,g,b);
			this.TransparencyKey = this.BackColor;

            _timer.Interval = 100;
            _timer.Tick += new EventHandler(MouseTimer_Tick);
            _timer.Start();

            //GlobalMouseHook.CreateHook();
            //GlobalMouseHook.Move += new ColorPicker.GlobalMouseHook.MouseEventHandlerExt(GlobalMouseHook_Move);
            //GlobalMouseHook.LeftButtonDown += new ColorPicker.GlobalMouseHook.MouseEventHandlerExt(GlobalMouseHook_MouseDown);
            //GlobalMouseHook.RightButtonDown += new ColorPicker.GlobalMouseHook.MouseEventHandlerExt(GlobalMouseHook_MouseDown);

		}

        //private void GlobalMouseHook_Move(Point pt)
        //{
        //    UpdatePosition();
        //}

        //private void GlobalMouseHook_MouseDown(Point pt)
        //{
        //    if (!_captureMouse) this.Close();
        //}

        //protected override void OnClosed(EventArgs e)
        //{
        //    GlobalMouseHook.DestroyHook();
        //    base.OnClosed(e);
        //}


		
		private const int OFFSET_MOUSE	= 5;
		private const int OFFSET_BORDER = 10;
		private const int OFFSET_FILL	= 15;

        Point _lastMousePosition = Point.Empty;

		private void UpdatePosition()
		{
            Point pt = Control.MousePosition;
            if (_lastMousePosition == pt) return;

            _lastMousePosition = pt;

			Rectangle workingArea = SystemInformation.WorkingArea;

			if( pt.X > workingArea.Right  - this.Width  ) pt.X -= this.Width  - 2*OFFSET_MOUSE;
			if( pt.Y > workingArea.Bottom - this.Height ) pt.Y -= this.Height - 2*OFFSET_MOUSE; 	
			pt.X -= OFFSET_MOUSE;
			pt.Y -= OFFSET_MOUSE;
			
			if( this.Location != pt) this.Location = pt;


            this.Invalidate();

			if( _captureMouse )  this.Activate();


		}

        protected override void OnLocationChanged(EventArgs e)
        {
            UpdatePosition();
            base.OnLocationChanged(e);
        }
        protected override void OnMouseLeave(EventArgs e)
        {
            UpdatePosition();
            base.OnMouseLeave(e);
        }

        protected override void OnMouseMove(MouseEventArgs e)
        {
            UpdatePosition();
            base.OnMouseMove(e);
        }

        private void MouseTimer_Tick(object sender, EventArgs e)
        {
            UpdatePosition();
        }

        protected override void OnMouseDown(MouseEventArgs e)
        {

            base.OnMouseDown(e);

            if (e.Button == MouseButtons.Right)
                this.DialogResult = DialogResult.Cancel;
            else
                this.DialogResult = DialogResult.OK;

            Point pt = Control.MousePosition;
            _color = SafeNativeMethods.GetPixelColor(pt);

            this.Close();

        }

		protected override void OnKeyDown(KeyEventArgs e)
		{
			base.OnKeyDown (e);

			if( e.KeyData == Keys.Cancel || e.KeyData == Keys.Escape )
			{
				this.DialogResult = DialogResult.Cancel;		
				this.Close();				
			}
		}



		private Color _color = Color.Empty;
		public Color Color
		{
			get{ return _color;}
		}



		bool _captureMouse  = true;


        protected override void OnPaint(PaintEventArgs e)
        {
            PaintBackgroundColor(e);

        }


        private void PaintBackgroundColor(PaintEventArgs e)
        {
            Point pt = Control.MousePosition;
            _color = SafeNativeMethods.GetPixelColor(pt);

            GraphicsContainer gc = e.Graphics.BeginContainer();
            e.Graphics.SmoothingMode = SmoothingMode.HighSpeed;
            if (_captureMouse)
                using (SolidBrush pxBrush = new SolidBrush(_color))
                {
                    pt = PointToClient(pt);
                    RectangleF rectPixel = new RectangleF(pt, new SizeF(2, 2));
                    rectPixel.X -= 0.5f;
                    rectPixel.Y -= 0.5f;
                    e.Graphics.FillRectangle(pxBrush, rectPixel);
                }

            Rectangle clientRect = this.ClientRectangle;

            using (SolidBrush brush = new SolidBrush(_color))
            {
                Rectangle rectFill = clientRect;
                rectFill.Inflate(-OFFSET_FILL, -OFFSET_FILL);
                e.Graphics.FillRectangle(brush, rectFill);

            }

            using (Pen pen = new Pen(SystemColors.ControlDarkDark, 1f))
            {
                Rectangle rectBorder = clientRect;
                rectBorder.Inflate(-OFFSET_BORDER, -OFFSET_BORDER);
                rectBorder.Width--;
                rectBorder.Height--;
                e.Graphics.DrawRectangle(pen, rectBorder);
            }

           e.Graphics.EndContainer(gc);

        }

	}
}
